package com.ycy.state;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.BDDAssertions.then;

import org.junit.Test;

public class EntranceMachineTest {

  @Test
  public void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    then(result).isEqualTo("opened");
    then(entranceMachine.getState()).isEqualTo(EntranceMachineState.UNLOCKED);
  }

  @Test
  public void should_be_locked_and_alarm_when_pass_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.PASS);

    then(result).isEqualTo("alarm");
    then(entranceMachine.getState()).isEqualTo(EntranceMachineState.LOCKED);
  }

  @Test
  public void should_fail_when_execute_invalid_action_given_a_entrance_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    assertThatThrownBy(() -> entranceMachine.execute(null))
            .isInstanceOf(InvalidActionException.class);
  }

  @Test
  public void should_locked_when_pass_given_a_entrance_machine_with_unlocked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.UNLOCKED);

    String result = entranceMachine.execute(Action.PASS);

    then(result).isEqualTo("closed");
    then(entranceMachine.getState()).isEqualTo(EntranceMachineState.LOCKED);
  }

  @Test
  public void should_refund_and_unlocked_when_insert_coin_given_a_entrance_machine_with_unlocked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.UNLOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    then(result).isEqualTo("refund");
    then(entranceMachine.getState()).isEqualTo(EntranceMachineState.UNLOCKED);
  }

}
